/**
 * Esta clase modela la entidad Machine. Machine procesa los trabajos enviados
 * por el Sender "CPU".
 */
package factory;

import eduni.simanim.*;
import eduni.simjava.*;
import eduni.simjava.distributions.Sim_normal_obj;

/**
 *
 * @author eagle
 */
public class Machine extends Sim_entity {

    //variables para el control de la simulacion
    //Puertos de salida y entrada
    private Sim_port in, out;
    //Estado de la entidad: ocupada u ociosa 
    private int state;
    private Sim_normal_obj delay;
    private static final int IDLE = 0;
    private static final int BUSY = 1;
    //Objeto para los calculos estdisticos
    private Sim_stat stat;

    //construct entity
    /**
     *
     * @param name nombre de la entidad
     * @param hold Espera
     * @param x coordenada x
     * @param y coordenada y
     */
    public Machine(String name, double hold, int x, int y) {
        super(name, "machine", x, y);

        /* @param port_name 
         * @param image_name 
         * @param side 
         * @param pos
         */
        in = new Sim_port("in", "port", Anim_port.TOP, 10);
        add_port(in);
        out = new Sim_port("out", "port", Anim_port.BOTTOM, 10);
        add_port(out);
        state = IDLE;

        /**
         * @param name Nombre del parametro
         * @param type Ubicacion del parametro
         * @param value Valor Inicial
         */
        add_param(new Anim_param("State", Anim_param.STATE, "idle"));

        //Asumimos que el tiempo de procesasamiento de los trabajos por parte de las
        //maquinas sigue una distribucion normal
        /**
         * Se genera un delay aleatorio basado en una distribucion Normal.
         *
         * @param name Nombre asociado con la instancia actual
         * @param mean La media de la distribucion
         * @param variance La varianza de la distribucion
         * @param seed Semilla inicial para generar el delay.
         */
        delay = new Sim_normal_obj("", hold, hold / 10.0, (int) System.currentTimeMillis());

         //estadistica
       
        stat = new Sim_stat();
        stat.add_measure(Sim_stat.THROUGHPUT);
        stat.add_measure(Sim_stat.RESIDENCE_TIME);
        stat.add_measure(Sim_stat.UTILISATION);
        set_stat(stat);

    }

    @Override
    public void body() {
        Sim_event ev = new Sim_event();
        double h;
        //agregamos trazas para cuando las maquinas esten ocupadas u ociosas
        dump_state();
        while (Sim_system.running()) {
            sim_wait(ev);
            sim_hold(0.01);
            state = BUSY;
            dump_state();
            /**
             * sample: genera un nuevo numero aleatorio (delay). Usa el metodo
             * Box-Muller.
             *
             * @return el siguiente numero aleatorio en la secuencia
             */
            h = delay.sample();
            sim_hold(h > 0 ? h : 0.01);
            state = IDLE;
            dump_state();
            sim_hold(0.01);

            /* 
             * @param: Puerto a travez del que se envia el evento.
             * @param: Intervalo de tiempo para el envio de eventos
             * @param: Tipo de evento, definido por el usuario.
             */
            sim_schedule(out, 0.0, 0);
            //Imprimimos la traza del mensaje
            if (AppletFactory.show_msg) {
                // Enviamos el Resultado del trabajo
                sim_trace(1, "S out R");
            }
            sim_schedule(in, 0.0, 0);

            //La maquina necesita mas trabajos
            //Se le dice al enrutador que se necesitan mas trabajos o que la maquina esta ociosa
            if (AppletFactory.show_msg) {
                sim_trace(1, "S in F");
            }
        }
    }

    public void dump_state() {
        if (state == IDLE) {
            sim_trace(1, "P idle");
        }
        if (state == BUSY) {
            sim_trace(1, "P busy");
        }
    }
}
